#include "ServerManager.h"
#include <Windows.h>
#include <vector>
#include <ctime>
#include <cstdlib>


ServerManager::ServerManager(const QString &nickname, QGraphicsScene * scene, QVector<int> &startPositions): IManager(scene)
{
    InitializeCriticalSectionAndSpinCount(&m_cs_snapshot, 0x400);

    m_startPositions = startPositions;
    m_ptr_messageManager = new ServerMessageManager();


    //connections from ServerManager signals to ServerMessageManager slots
    QObject::connect(this, SIGNAL(signalAcceptNickname(int,int)),
            m_ptr_messageManager, SLOT(slotSC_CONN_ACCEPTED(int,int)));

    QObject::connect(this, SIGNAL(signalRejectNickname(int,QString)),
            m_ptr_messageManager, SLOT(slotSC_CONN_REJECTED(int,QString)));

    QObject::connect(this, SIGNAL(signalFire(int)),
            m_ptr_messageManager, SLOT(slotSC_FIRE(int)));

    QObject::connect(this, SIGNAL(signalGameOver(int)),
            m_ptr_messageManager, SLOT(slotSC_GAME_END(int)));

    QObject::connect(this, SIGNAL(signalStart()),
            m_ptr_messageManager, SLOT(slotSC_GAME_START()));

    QObject::connect(this, SIGNAL(signalMove(int)),
            m_ptr_messageManager, SLOT(slotSC_MOVE(int)));

    QObject::connect(this, SIGNAL(signalPlaylistToAll(QString)),
            m_ptr_messageManager, SLOT(slotSC_PLAYERLIST(QString)));

    QObject::connect(this, SIGNAL(signalPlaylist(int,QString)),
            m_ptr_messageManager, SLOT(slotSC_PLAYERLIST(int,QString)));

    QObject::connect(this, SIGNAL(signalSendMap(int,int,QString,int,int,int,int)),
            m_ptr_messageManager, SLOT(slotSC_SEND_MAP(int,int,QString,int,int,int,int)));

    QObject::connect(this, SIGNAL(signalSendSnapshot(QString)),
            m_ptr_messageManager, SLOT(slotSC_SEND_SNAPSHOT(QString)));

    QObject::connect(this, SIGNAL(signalStopFire(int)),
            m_ptr_messageManager, SLOT(slotSC_STOP_FIRE(int)));

    QObject::connect(this, SIGNAL(signalStopMove(int)),
            m_ptr_messageManager, SLOT(slotSC_STOP_MOVE(int)));

    QObject::connect(this, SIGNAL(signalTurn(int,char)),
            m_ptr_messageManager, SLOT(slotSC_TURN(int,char)));


    //connections from ServerMessageManager signals to ServerManager slots
    QObject::connect(m_ptr_messageManager, SIGNAL(signalClientDisconnected(int)),
            this, SLOT(slotDisconnect(int)));
//    QObject::connect(m_ptr_messageManager, SIGNAL(signalConnectionError()),
//            this, SLOT(slot));
    QObject::connect(m_ptr_messageManager, SIGNAL(signalDISCONNECT(int)),
            this, SLOT(slotDisconnect(int)));
    QObject::connect(m_ptr_messageManager, SIGNAL(signalFIRE(int)),
            this, SLOT(slotFire(int)));
    QObject::connect(m_ptr_messageManager, SIGNAL(signalMOVE(int)),
            this, SLOT(slotMove(int)));
    connect(m_ptr_messageManager, SIGNAL(signalPlayerDisconnected(int)),
            this, SLOT(slotDisconnect(int)));    //to deal with bad disconnect
    QObject::connect(m_ptr_messageManager, SIGNAL(signalSEND_NICK(int,QString)),
            this, SLOT(slotSetNickname(int,QString)));
    QObject::connect(m_ptr_messageManager, SIGNAL(signalSTOP_FIRE(int)),
            this, SLOT(slotStopFire(int)));
    QObject::connect(m_ptr_messageManager, SIGNAL(signalSTOP_MOVE(int)),
            this, SLOT(slotStopMove(int)));
    QObject::connect(m_ptr_messageManager, SIGNAL(signalTURN(int,char)),
            this, SLOT(slotTurn(int,char)));
//    connect(m_ptr_messageManager, SIGNAL(signalUNKNOWN_COMMAND(QString)),
//            this, SLOT(slot));        //TODO to deal with bad command

    my_nick = nickname;
}


ServerManager::~ServerManager()
{
    emit signalDisconnect();

    delete m_ptr_messageManager;
}


void ServerManager::slotCreateMap(int width, int height, const QString& map,
                                  int health, int motion_speed, int bullet_speed, int fire_rate)
{
    if (m_ptr_gameData != NULL)
        return;
    m_ptr_gameData = new GameData();
    IManager::slotCreateMap(width, height, map, health, motion_speed, bullet_speed, fire_rate);
    qDebug() << m_startPositions[3];
    qDebug() << m_startPositions[4];
    Tank tank(m_startPositions[0]*25, m_startPositions[1]*25, 'L', m_motion_speed, 0, 0, m_max_health);
    tank.SetNick(my_nick);
    tank.addToScene(m_ptr_scene);
    m_ptr_gameData->my_nick = my_nick;
    m_ptr_gameData->my_id = 0;
    m_players.insert(std::make_pair(0, Player()));
    qDebug()<<"Create tanck in Create map Server";
    m_ptr_gameData->tanks.push_back(tank);

    m_map = map;
}


void ServerManager::slotUpdate()
{
    EnterCriticalSection(&m_cs_snapshot);

    if (game_status != GAME_IN_PROC)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    // Time stamp
    long timestamp = clock();
    bool need_snapshot = false;
    bool need_snapshot0;
    while (timestamp > m_timestamp)
    {
        advance(timestamp, need_snapshot0);
        if (need_snapshot0)
            need_snapshot = true;
    }

    if (need_snapshot)
    {
        emit signalSendSnapshot(constructSnapshot());
    }

    m_ptr_gameData->DrawAll();

    int alive = 0;
    int winner = 0;
    for (std::list<Tank>::iterator iter = m_ptr_gameData->tanks.begin(); iter != m_ptr_gameData->tanks.end(); ++iter)
    {
        if (iter->GetHealth() > 0)
        {
            alive++;
            winner = iter->GetID();
        }
    }
    if (alive < 2)
    {
        emit signalGameOver(winner);
    }

    LeaveCriticalSection(&m_cs_snapshot);
}


void ServerManager::slotStart()
{
    EnterCriticalSection(&m_cs_snapshot);

    if (game_status >= GAME_STARTED || m_ptr_gameData == NULL)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    // Check number of players and their nicknames:
    if (m_ptr_gameData->tanks.size() < 0)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    game_status = GAME_IN_PROC;

    // Time stamp
    m_timestamp = clock();

    // !!!!!!!!!!!!!
    // Send "START" message
    emit signalStart();
    emit signalSendMap(
                m_ptr_gameData->field->GetWidth(),
                m_ptr_gameData->field->GetHeight(),
                m_map,
                m_max_health,
                m_motion_speed,
                m_bullet_speed,
                m_fire_rate);
    emit signalSendSnapshot(constructSnapshot());

    // Draw
    qDebug()<<"drow tank";
    m_ptr_gameData->DrawAll();

    LeaveCriticalSection(&m_cs_snapshot);
}


void ServerManager::slotFire(int tank_id)
{
    EnterCriticalSection(&m_cs_snapshot);

    if (game_status != GAME_IN_PROC)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    std::map<int, Player>::iterator pl = m_players.find(tank_id);
    if (pl->second.firing)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    pl->second.firing = true;

    // Send "FIRE" message to all
    emit signalFire(tank_id);

    LeaveCriticalSection(&m_cs_snapshot);
}


void ServerManager::slotStopFire(int tank_id)
{
    EnterCriticalSection(&m_cs_snapshot);

    if (game_status != GAME_IN_PROC)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    std::map<int, Player>::iterator pl = m_players.find(tank_id);
    if (! pl->second.firing)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }
    pl->second.firing = false;

    // Send "STOP_FIRE" message to all
    emit signalStopFire(tank_id);

    LeaveCriticalSection(&m_cs_snapshot);
}


void ServerManager::slotMove(int tank_id)
{
    EnterCriticalSection(&m_cs_snapshot);

    if (game_status != GAME_IN_PROC)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    std::map<int, Player>::iterator pl = m_players.find(tank_id);
    std::list<Tank>::iterator iter;
    switch (pl->second.action)
    {
    case 'S':
        pl->second.action = 'M';
        break;
    case 'M':
        if (pl->second.queueEmpty())
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "S")
        {
            pl->second.action_queue = "";
        }
        else if (pl->second.action_queue == "R")
        {
            pl->second.action_queue = "RM";
        }
        else if (pl->second.action_queue == "L")
        {
            pl->second.action_queue = "LM";
        }
        else if (pl->second.action_queue == "RM")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "RR")
        {
            pl->second.action_queue = "RRM";
        }
        else if (pl->second.action_queue == "LM")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "LL")
        {
            pl->second.action_queue = "LLM";
        }
        else if (pl->second.action_queue == "RRM")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "LLM")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else
        { // Unrecognized sequence
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        break;
    case 'L':
    case 'R':
        if (pl->second.queueEmpty())
        {
            pl->second.action_queue = "M";
        }
        else if (pl->second.action_queue == "M")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "R")
        {
            pl->second.action_queue = "RM";
        }
        else if (pl->second.action_queue == "L")
        {
            pl->second.action_queue = "LM";
        }
        else if (pl->second.action_queue == "RM")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "RR")
        {
            pl->second.action_queue = "RRM";
        }
        else if (pl->second.action_queue == "LM")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "LL")
        {
            pl->second.action_queue = "LLM";
        }
        else if (pl->second.action_queue == "RRM")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "LLM")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        break;
    default:
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    // Send "MOVE" message to all
    emit signalMove(tank_id);

    LeaveCriticalSection(&m_cs_snapshot);
}


void ServerManager::slotStopMove(int tank_id)
{
    EnterCriticalSection(&m_cs_snapshot);

    if (game_status != GAME_IN_PROC)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    std::map<int, Player>::iterator pl = m_players.find(tank_id);
    std::list<Tank>::iterator iter;
    for (iter = m_ptr_gameData->tanks.begin(); iter != m_ptr_gameData->tanks.end(); ++iter)
    {
        if (iter->GetID() == tank_id)
            break;
    }

    switch (pl->second.action)
    {
    case 'M':
        if (pl->second.queueEmpty())
        {
            pl->second.action_queue = "S";
        }
        else if (pl->second.action_queue == "S")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "R")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "L")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "RM")
        {
            pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "RR")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "LM")
        {
            pl->second.action_queue = "L";
        }
        else if (pl->second.action_queue == "LL")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "RRM")
        {
            pl->second.action_queue = "RR";
        }
        else if (pl->second.action_queue == "LLM")
        {
            pl->second.action_queue = "LL";
        }
        else
        { // Unrecognized sequence
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        break;
    case 'L':
    case 'R':
        if (pl->second.queueEmpty())
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "M")
        {
            pl->second.action_queue = "";
        }
        else if (pl->second.action_queue == "R")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "L")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "RM")
        {
            pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "RR")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "LM")
        {
            pl->second.action_queue = "L";
        }
        else if (pl->second.action_queue == "LL")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "RRM")
        {
            pl->second.action_queue = "RR";
        }
        else if (pl->second.action_queue == "LLM")
        {
            pl->second.action_queue = "LL";
        }
        else
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        break;
    case 'S':
    default:
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    // Send "STOP_MOVE" message to all
    emit signalStopMove(tank_id);

    LeaveCriticalSection(&m_cs_snapshot);
}


void ServerManager::slotTurn(int tank_id, char direction)
{
    qDebug()<<"enter to the ROTATE slotTurn  direction = "<<direction;
    EnterCriticalSection(&m_cs_snapshot);

    if (game_status != GAME_IN_PROC)
    {
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }

    std::map<int, Player>::iterator pl = m_players.find(tank_id);
    qDebug()<<"ServerManager::slotTurn(int tank_id, char direction) "<< tank_id;
    std::list<Tank>::iterator iter;
    for (iter = m_ptr_gameData->tanks.begin(); iter != m_ptr_gameData->tanks.end(); ++iter)
    {
        if (iter->GetID() == tank_id)
            break;
    }
    qDebug()<<pl->second.action<< "action";
    switch (pl->second.action)
    {
    case 'M':
        if (pl->second.queueEmpty())
        {
            pl->second.action_queue = direction;
        }
        else if (pl->second.action_queue == "S")
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        else if (pl->second.action_queue == "R")
        {
            if (direction == 'R')
                pl->second.action_queue = "RR";
            else
                pl->second.action_queue = "S";
        }
        else if (pl->second.action_queue == "L")
        {
            if (direction == 'L')
                pl->second.action_queue = "LL";
            else
                pl->second.action_queue = "S";
        }
        else if (pl->second.action_queue == "RM")
        {
            if (direction == 'R')
                pl->second.action_queue = "RR";
            else
                pl->second.action_queue = "S";
        }
        else if (pl->second.action_queue == "RR")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "LM")
        {
            if (direction == 'L')
                pl->second.action_queue = "LL";
            else
                pl->second.action_queue = "S";
        }
        else if (pl->second.action_queue == "LL")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "RRM")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "LLM")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else
        { // Unrecognized sequence
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        break;
    case 'L':
        if (pl->second.queueEmpty())
        {
            pl->second.action_queue = direction;
        }
        else if (pl->second.action_queue == "M")
        {
            pl->second.action_queue = direction;
        }
        else if (pl->second.action_queue == "R")
        {
            if (direction == 'R')
                pl->second.action_queue = "RR";
            else
                pl->second.action_queue = "";
        }
        else if (pl->second.action_queue == "L")
        {
            if (direction == 'R')
                pl->second.action_queue = "";
            else
                pl->second.action_queue = "LL";
        }
        else if (pl->second.action_queue == "RM")
        {
            if (direction == 'R')
                pl->second.action_queue = "RR";
            else
                pl->second.action_queue = "";
        }
        else if (pl->second.action_queue == "RR")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "LM")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "LL")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "RRM")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "LLM")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
              pl->second.action_queue = "R";
        }
        else
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        break;
    case 'R':
        if (pl->second.queueEmpty())
        {
            pl->second.action_queue = direction;
        }
        else if (pl->second.action_queue == "M")
        {
            pl->second.action_queue = direction;
        }
        else if (pl->second.action_queue == "R")
        {
            if (direction == 'R')
                pl->second.action_queue = "RR";
            else
                pl->second.action_queue = "";
        }
        else if (pl->second.action_queue == "L")
        {
            if (direction == 'R')
                pl->second.action_queue = "";
            else
                pl->second.action_queue = "LL";
        }
        else if (pl->second.action_queue == "RM")
        {
            if (direction == 'R')
                pl->second.action_queue = "RR";
            else
                pl->second.action_queue = "";
        }
        else if (pl->second.action_queue == "RR")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "LM")
        {
            if (direction == 'R')
                pl->second.action_queue = "";
            else
                pl->second.action_queue = "LL";
        }
        else if (pl->second.action_queue == "LL")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "RRM")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
                pl->second.action_queue = "R";
        }
        else if (pl->second.action_queue == "LLM")
        {
            if (direction == 'R')
                pl->second.action_queue = "L";
            else
              pl->second.action_queue = "R";
        }
        else
        {
            LeaveCriticalSection(&m_cs_snapshot);
            return;
        }
        break;
    case 'S':
    default:
        LeaveCriticalSection(&m_cs_snapshot);
        return;
    }


    // Send "TURN" message to all
    emit signalTurn(tank_id, direction);

    LeaveCriticalSection(&m_cs_snapshot);
}


void ServerManager::slotSetNickname(int localDescriptor, QString nick)
{
    qDebug()<<"Server slotSetNickname ";
    if (game_status >= GAME_STARTED)
        return;

    if (testNickname(nick))
    {
        qDebug() << "ServerManager::slotSetNickname(int localDescriptor, QString nick)";
        int i;
        for (i = 0; i < m_ptr_gameData->tanks.size(); ++i)
        {
            std::list<Tank>::iterator iter;
            for (iter = m_ptr_gameData->tanks.begin(); iter != m_ptr_gameData->tanks.end(); ++iter)
            {
                if (iter->GetID() == i)
                    break;
            }
            if (iter == m_ptr_gameData->tanks.end())    //inserting in exxisting free position
            {
                qDebug()<<"Server slotSetNickname ";
                qDebug()<<"Add tank "<< m_startPositions[i]<<" "<<m_startPositions[i+1]<<" "<<i;

                Tank *tank = new Tank(m_startPositions[i], m_startPositions[i+1], 'R', m_motion_speed, 0, i, m_max_health);
                tank->SetNick(nick);
                m_ptr_gameData->tanks.push_back(*tank);
                m_players.insert(std::make_pair(i, Player()));
                emit signalAcceptNickname(localDescriptor, i);
                qDebug()<<"!!!!!!!!!!!Before PlayerListConstruct 1";
                emit signalPlaylistToAll(constructPlayerlist());
                return;
            }
        }

        //inserting in end
        if (i < 8)
        {
            qDebug()<<"Server slotSetNickname ";
            qDebug()<<"Add tank "<< m_startPositions[i]<<" "<<m_startPositions[i+1]<<" "<<i;

            Tank tank(m_startPositions[i], m_startPositions[i+1], 'R', m_motion_speed, 0, i, m_max_health);
            tank.SetNick(nick);
            m_ptr_gameData->tanks.push_back(tank);
            m_players.insert(std::make_pair(i, Player()));
            emit signalAcceptNickname(localDescriptor, i);
            qDebug()<<"!!!!!!!!!!!Before PlayerListConstruct 2 "<<localDescriptor<<" "<<i;
            emit signalPlaylistToAll(constructPlayerlist());
            return;
        }

    }
    else
    {
        emit signalRejectNickname(localDescriptor, QString("Nickname_is_not_allowed"));
    }
}


void ServerManager::slotKeyPresEvent(QKeyEvent * event)
{
    std::map<int, Player>::iterator pl = m_players.find(m_ptr_gameData->my_id);
    std::list<Tank>::iterator tank = m_ptr_gameData->tanks.begin();
    while (tank->GetID() != m_ptr_gameData->my_id)
        ++tank;

    if (game_status == GAME_IN_PROC)
    {
        int iDir;
        switch (event->key())
        {
        case Qt::Key_Control:
            slotFire(m_ptr_gameData->my_id);
            return;
        case Qt::Key_Left:
            //pl->second.action='L';
            iDir = 1;
            break;
        case Qt::Key_Right:
            //pl->second.action='R';
            iDir = 3;
            break;
        case Qt::Key_Up:
            //pl->second.action='U';
            iDir = 0;
            break;
        case Qt::Key_Down:
           // pl->second.action='D';
            iDir = 2;
            break;
        default:
            if (event->modifiers() & Qt::ControlModifier)
            {
                slotFire(m_ptr_gameData->my_id);
            }
            else
            {
                slotStopFire(m_ptr_gameData->my_id);
            }
            return;
        }
        /*
        int iDirCur;
        if(tank->GetDirection()!= iDir)
        {
            switch(tank->GetDirection())
            {
            case 'U':
                iDirCur = 0;
                break;
            case 'L':
                iDirCur = 1;
                break;
            case 'D':
                iDirCur = 2;
                break;
            case 'R':
                iDirCur = 3;
                break;
            }
            if(iDirCur > iDir)
                tank->rotate(-90);
            else
                tank->rotate(+90);
        }
        else
        {
            switch(iDirCur)
            case 0:
                tank->SetPosY
        }*/
        int change;
        switch (tank->GetDirection())
        {
        case 'U':
            change = 0;
            break;
        case 'R':
            change = 1;
            break;
        case 'D':
            change = 2;
            break;
        default:
            change = 3;
        }
        if (pl->second.action != 'S')
        {
            if (pl->second.action == 'R')
                change++;
            else if (pl->second.action == 'L')
                change--;
            for (int i = 0; i < pl->second.action_queue.length(); ++i)
            {
                if (pl->second.action_queue.at(i).toAscii() == 'R')
                    change++;
                else if (pl->second.action_queue.at(i).toAscii() == 'L')
                    change--;
            }
        }
        while (change < 0)
            change += 4;
        change %= 4;

        qDebug()<<iDir<<"  "<< change;
        if (change < -2)
            change += 4;
        if (change > 2)
            change -= 4;
        while (change > 0)
        {
            change--;
            pl->second.action='R';
            slotTurn(m_ptr_gameData->my_id, 'R');
        }
        while (change < 0)
        {
            change++;
            pl->second.action='L';
            slotTurn(m_ptr_gameData->my_id, 'L');
        }

        slotMove(m_ptr_gameData->my_id);

        if (event->modifiers() & Qt::ControlModifier)
        {
            slotFire(m_ptr_gameData->my_id);
        }
        else
        {
            slotStopFire(m_ptr_gameData->my_id);
        }
    }
}


void ServerManager::slotKeyReleaseEvent(QKeyEvent *event)
{
    if (game_status == GAME_IN_PROC)
    {
        switch (event->key())
        {
        case Qt::Key_Control:
            slotStopFire(m_ptr_gameData->my_id);
            break;
        case Qt::Key_Left:
        case Qt::Key_Right:
        case Qt::Key_Up:
        case Qt::Key_Down:
            slotStopMove(m_ptr_gameData->my_id);
            if (!(event->modifiers() & Qt::ControlModifier))
                slotStopFire(m_ptr_gameData->my_id);
        }
    }
}


void ServerManager::slotDisconnect(int player_id)
{
    EnterCriticalSection(&m_cs_snapshot);

    m_players.erase(m_players.find(player_id));
    std::list<Tank>::iterator iter;
    for (iter = m_ptr_gameData->tanks.begin(); iter != m_ptr_gameData->tanks.end(); ++iter)
    {
        if (iter->GetID() == player_id)
            break;
    }
    m_ptr_gameData->tanks.erase(iter);

    emit signalPlaylistToAll(constructPlayerlist());

    LeaveCriticalSection(&m_cs_snapshot);
}


void ServerManager::slotRequestPlaylist(int socketDescriptor)
{
    emit signalPlaylist(socketDescriptor, constructPlayerlist());
}


void ServerManager::slotRequestMap()
{
    emit signalSendMap(
                m_ptr_gameData->field->GetWidth(),
                m_ptr_gameData->field->GetHeight(),
                m_map,
                m_max_health,
                m_motion_speed,
                m_bullet_speed,
                m_fire_rate);
}


QString ServerManager::constructPlayerlist()
{
    QString pl = "";
    std::list<Tank>::iterator iter;
    for (iter = m_ptr_gameData->tanks.begin(); iter != m_ptr_gameData->tanks.end(); ++iter)
    {
        pl += QString::number(iter->GetID());
        pl += delimetrs::delim;
        pl += iter->GetNick();
        pl += delimetrs::delim;
        qDebug()<<iter->GetID()<<" "<< delimetrs::delim<<" "<<iter->GetNick();
    }
    pl.remove(pl.size() - 1, 1);
    qDebug()<< "QString ServerManager::constructPlayerlist()"<<pl;
    return pl;
}


QString ServerManager::constructSnapshot()
{
    QString ssh = "";
    char buf[30];
    ssh += itoa(m_ptr_gameData->tanks.size(),buf,10);
    for (std::list<Tank>::iterator iter = m_ptr_gameData->tanks.begin(); iter != m_ptr_gameData->tanks.end(); ++iter)
    {
        ssh += delimetrs::delim;
        ssh += itoa(iter->GetID(),buf,10);
        ssh += delimetrs::delim;
        ssh += itoa(iter->GetHealth(),buf,10);
        ssh += delimetrs::delim;
        ssh += itoa(iter->GetPosX(),buf,10);
        ssh += delimetrs::delim;
        ssh += itoa(iter->GetPosY(),buf,10);
        ssh += delimetrs::delim;
        ssh += iter->GetCurrentAction();
        ssh += delimetrs::delim;
        ssh += iter->GetDirection();
        ssh += delimetrs::delim;
        ssh += itoa(static_cast<int>(iter->GetProgress()),buf,10);
    }
    for (std::list<Bullet>::iterator iter = m_ptr_gameData->bullets.begin(); iter != m_ptr_gameData->bullets.end(); ++iter)
    {
        ssh += delimetrs::delim;
        ssh += itoa(iter->GetID(),buf,10);
        ssh += delimetrs::delim;
        ssh += itoa(iter->GetPosX(),buf,10);
        ssh += delimetrs::delim;
        ssh += itoa(iter->GetPosY(),buf,10);
        ssh += delimetrs::delim;
        ssh += iter->GetDirection();
        ssh += delimetrs::delim;
        ssh += itoa(static_cast<int>(iter->GetProgress()),buf,10);
        ssh += delimetrs::delim;
    }
    if (m_ptr_gameData->bullets.size() != 0)
    {
        ssh.remove(ssh.size() - 1, 1);
    }
    return ssh;
}
